home *** CD-ROM | disk | FTP | other *** search
- /*
- * Module v_doscur MSDOS-specific video routines
- * Author larry gensch, ESQ
- *
- * Copyright (c) 1987, 1988, 1989
- * by Larry Gensch / 104 Lowell Road / Salem, NH 03079
- *
- * This code may be included in any work, public or private, with the
- * exception of creating a commercial curses-compatible subroutine
- * library. (In other words, use the code all you want, but please don't
- * rip off the author by reselling this code as your own).
- *
- * If you make modifications to this code (specifically, enhancements that
- * are compatible with System V.x curses), please send them to larry gensch at
- * the address above to be considered for inclusion in subsequent releases.
- * Any machine specific implementation modules (similar to v_doscur.c) for
- * other machines are welcomed.
- *
- * v_doscur.c is a machine-specific driver for curses that writes directly to
- * the memory mapped video display. Currently, there is NO support for color
- * or routines using PADS (windows larger than the physical terminal screen).
- * To port curses to a new machine, this is the module that will have to be
- * reimplemented.
- *
- */
-
- #include "curses.h"
-
- #include <ctype.h>
- #include <stdarg.h>
- #include <stdlib.h>
-
- /*
- * EXPORT is used to show entry points into this module. Simply grep
- * using the pattern '^EXPORT' to list them out.
- */
-
- #ifndef EXPORT
- #define EXPORT
- #endif
-
- static unsigned GetDS (void);
- static void Doinit (int *lines, int *cols);
- static void Mapscreen (WINDOW *win);
- static void Dispscreen (void);
- static void Setcursor (int line, int col);
- static void Dosrestore (void);
- static bool Kbhit (void);
- static int Getkey (bool raw);
-
- /*
- * ms_init() - Perform any necessary initializations of the terminal or to
- * the implementation module. The LINES and COLS variables should be set
- * as well.
- */
-
- EXPORT bool ms_init (void)
- {
- Doinit(&LINES, &COLS);
-
- return TRUE;
- }
-
- /*
- * ms_refresh() - Refresh a WINDOW image onto our internal representation
- * of our screen. outflag specifies whether or not the actual display
- * should be updated. Returns ERR if an error occurred.
- *
- * Note: If win is NULL, just update the display.
- */
-
- EXPORT int ms_refresh (WINDOW *win, bool outflag)
- {
- static int Lastcol = 0; /* Save latest cursor position. No provision here for */
- static int Lastrow = 0; /* invisible cursor. */
-
- if (win)
- Mapscreen(win);
-
- if (win) {
- if (! win->_leave) {
- Lastrow = _CURS_CURSOR_SCREEN_ROW(win);
- Lastcol = _CURS_CURSOR_SCREEN_COL(win);
- }
- }
-
- if (outflag) {
- Dispscreen();
- Setcursor(Lastrow, Lastcol);
- }
-
- return OK;
- }
-
- /*
- * ms_end() - Restore the display so that a non-curses application can use
- * it. (Restore terminal modes, move cursor to lower left corner, etc.)
- */
-
- EXPORT bool ms_end (void)
- {
- Setcursor(LINES - 1, 0);
- return OK;
- }
-
- /*
- * ms_restore_scrn() - Allows user to repaint screen as it was before curses initialization.
- */
-
- EXPORT void ms_restore_scrn (void)
- {
- Dosrestore();
- }
-
- /*
- * ms_beep() - Sound the workstation alarm. If flag is TRUE, then the
- * workstation should be flashed, instead, if possible.
- */
-
- EXPORT void ms_beep (int flag)
- {
- fputc('\a', stderr);
- }
-
- /*
- * ms_kbinp() - Get input from keyboard.
- */
-
- EXPORT int ms_kbinp (WINDOW *win, bool raw, bool cbreak)
- {
- if (win->_nodelay) {
- if (! Kbhit())
- return ERR;
- }
-
- Setcursor(_CURS_CURSOR_SCREEN_ROW(win),
- _CURS_CURSOR_SCREEN_COL(win));
- return Getkey(raw);
- }
-
- /*
- * ms_flushinp() - Throw away pending keyboard input.
- */
-
- EXPORT void ms_flushinp (void)
- {
- while (Kbhit()) getch();
- }
-
-
- /*
- * Alternate Character Set table:
- *
- * Line drawing characters are named as follows:
- *
- * t
- *
- * |
- * l --+-- r
- * |
- *
- * b
- *
- * ACS_trbl (t=top, r=right, b=bottom, l=left)
- *
- * Valid values for each placeholder:
- *
- * B (blank) S (single) D (double) T (thick)
- *
- * Curses (currently) only supports B and S.
- */
-
- EXPORT chtype acs_map[256] = {
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x801a, 0x801b, 0x8018, 0x8019, 0x0 ,
- 0x805b, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x0 ,
- 0x8004, 0x8030, 0x0 , 0x0 , 0x0 , 0x0 , 0x8078, 0x8071,
- 0x8032, 0x8068, 0x8059, 0x803f, 0x805a, 0x8040, 0x8045, 0x805f,
- 0x0 , 0x8044, 0x0 , 0x802d, 0x8043, 0x8034, 0x8041, 0x8042,
- 0x8033, 0x0 , 0x0 , 0x0 , 0x0 , 0x0 , 0x8007, 0x0 ,
- };
-
- /* -------------------------------------------- */
- /* Private routines and variables */
- /* -------------------------------------------- */
-
- static const unsigned Monobase = 0xB000;
- static const unsigned Colrbase = 0xB800;
-
- #if defined (__WATCOMC__) && defined (__386__)
- # define INT86_FN int386
- #else
- # define INT86_FN int86
- #endif
-
- typedef struct CHAR {
- char ch;
- char at;
- } CHAR;
-
- static CHAR *Screen; /* PC Screen image */
- static void *Oldscreen = NULL; /* Saved screen image */
- static unsigned Screenbase = 0; /* Segment for OUR machine */
-
- #define VIDEO_INT 0x10 /* Video interrupt */
-
- #define CUR_SIZE 0x1 /* Set cursor size */
- #define SET_POSN 0x2 /* Modify cursor posn */
- #define GET_POSN 0x3 /* Read current cursor posn */
- #define WRITE 0x9 /* Write character */
- #define WRITE_TTY 0xe /* Write char & move cursor */
- #define GET_VMODE 0xf /* Get video mode & disp pg */
-
- #undef getch /* Defn in conio.h */
-
- #include <dos.h>
- #include <string.h>
- #include <conio.h>
-
- static union REGS Regs; /* Used to talk to DOS */
- static int Xmax = 0; /* Number of columns */
- static int Ymax = 0; /* Number of rows */
-
- #define ATTR_NORM 0x07 /* Normal attr *lg* */
- #define ATTR_SOUT 0x70 /* Standout attr *lg* */
- #define ATTR_UOUT 0x01 /* Underline attr *lg* */
- #define ATTR_BOUT 0x80 /* Blinking attr *lg* */
- #define ATTR_BOLD 0x08 /* Bold attr *lg* */
-
- #define SCAN_BACKSPACE '\b' /* Backspace key */
- #define SCAN_EXIT 0x001B /* Exit key (ESC) */
- #define SCAN_CBACKSPACE 0x007F /* Ctrl + Backspace */
- #define SCAN_BTAB 0x010F /* Shift + Tab key */
- #define SCAN_F1 0x013B /* Function key 1 */
- #define SCAN_HOME 0x0147 /* Home key */
- #define SCAN_UP 0x0148 /* Up arrow */
- #define SCAN_PPAGE 0x0149 /* PgUp key */
- #define SCAN_LEFT 0x014B /* Left arrow */
- #define SCAN_RIGHT 0x014D /* Right arrow */
- #define SCAN_END 0x014F /* End key */
- #define SCAN_DOWN 0x0150 /* Down arrow */
- #define SCAN_NPAGE 0x0151 /* PgDn key */
- #define SCAN_IC 0x0152 /* Ins key */
- #define SCAN_DC 0x0153 /* Del key */
- #define SCAN_SF1 0x0154 /* Shift + F Key 1 */
- #define SCAN_CF1 0x015E /* Ctrl + F Key 1 */
- #define SCAN_AF1 0x0168 /* Alt + F Key 1 */
- #define SCAN_SLEFT 0x0173 /* Ctrl + Left arrow */
- #define SCAN_SRIGHT 0x0174 /* Ctrl + Right arrow */
- #define SCAN_SEND 0x0175 /* Ctrl + End key */
- #define SCAN_CNPAGE 0x0176 /* Ctrl + PgDn */
- #define SCAN_SHOME 0x0177 /* Ctrl + Home key */
- #define SCAN_CPPAGE 0x0184 /* Ctrl + PgUp */
-
- /*
- * GetDS() - Return the data segment as an unsigned value.
- */
-
- static unsigned GetDS (void)
- {
- struct SREGS seg;
-
- segread(&seg);
-
- return seg.ds;
- }
-
- /*
- * Doinit() - Perform our initializations, and set lines and columns.
- */
-
- static void Doinit (int *lines, int *cols)
- {
- register int i;
- CHAR *ptr;
- char *src_ptr;
-
- Regs.h.ah = GET_VMODE;
-
- INT86_FN( VIDEO_INT, &Regs, &Regs );
-
- *cols = Xmax = Regs.h.ah;
- *lines = Ymax = 25;
-
- if (Screen == NULL)
- Screen = (CHAR *)malloc(Xmax * Ymax * sizeof(CHAR));
-
- if (Screen == NULL) {
- fputs("v_doscur: memory allocation failure.\n", stderr);
- exit(1);
- }
-
- for (ptr = Screen, i = *lines * *cols; i >= 0; i--, ptr++) {
- ptr->ch = ' ';
- ptr->at = ATTR_NORM;
- }
-
- if (Regs.h.al == 7)
- Screenbase = Monobase;
- else
- Screenbase = Colrbase;
-
- if (Oldscreen == NULL)
- Oldscreen = malloc(Xmax * Ymax * 2);
-
- if (Oldscreen == NULL) {
- fputs("v_doscur: memory allocation failure.\n", stderr);
- exit(1);
- }
-
- #if defined (__WATCOMC__) && defined (__386__)
- src_ptr = (Screenbase << 4);
- memcpy(Oldscreen, src_ptr, Xmax * Ymax * 2);
- #else
- movedata(Screenbase, 0, GetDS(), (unsigned) Oldscreen, Xmax * Ymax * 2);
- #endif
- }
-
- /*
- * Mapscreen() - Copy the screen image given to us by CURSES into our
- * internal display representation.
- */
-
- static void Mapscreen (WINDOW *win)
- {
- int maxx, maxy, i_rw, i;
- chtype *src_ptr, attr;
- CHAR *sptr, *dst_ptr;
-
- if (win->_begy < Ymax && win->_begx < Xmax)
- {
- dst_ptr = Screen + (win->_begy * Xmax) + win->_begx;
- if (win->_flags & _ISPAD)
- {
- maxx = win->_pmap_maxx - win->_pmap_orgx; /* For pads, get # rows and columns to display. */
- maxy = win->_pmap_maxy - win->_pmap_orgy;
- src_ptr = win->_y + /* Point to 1st displayed character in pad. */
- ((win->_pmap_orgy * win->_xdim) +
- win->_pmap_orgx);
- }
- else
- {
- maxx = win->_maxx;
- maxy = win->_maxy;
- src_ptr = win->_y;
- }
-
- maxy = MIN(maxy, Ymax - win->_begy);
- maxx = MIN(maxx, Xmax - win->_begx);
-
- for (i_rw = 0; i_rw < maxy; i_rw++, /* Copy text from window to screen image. */
- dst_ptr += Xmax, src_ptr += win->_xdim)
- {
- for (i = 0; i < maxx; i++)
- {
- sptr = dst_ptr + i;
- attr = *(src_ptr + i) & A_ATTRIBUTES;
-
- sptr->ch = *(src_ptr + i) & A_CHARTEXT;
-
- if (attr & A_ALTCHARSET)
- sptr->ch |= 0x80;
-
- sptr->at = ATTR_NORM;
-
- if (attr & A_STANDOUT)
- sptr->at = ATTR_SOUT;
- if (attr & A_REVERSE)
- sptr->at = ATTR_SOUT;
- if (attr & A_UNDERLINE)
- sptr->at = ATTR_UOUT;
- if (attr & A_BOLD)
- sptr->at |= ATTR_BOLD;
- if (attr & A_BLINK)
- sptr->at |= ATTR_BOUT;
- }
- }
- }
- }
-
- /*
- * Dispscreen() - Make the physical screen look like our internal screen.
- */
-
- static void Dispscreen (void)
- {
- #if defined (__WATCOMC__) && defined (__386__)
- char *src_ptr = (Screenbase << 4);
- memcpy(src_ptr, Screen, Xmax * Ymax * 2);
- #else
- movedata(GetDS(), (unsigned) Screen, Screenbase, 0, Xmax * Ymax * 2);
- #endif
- }
-
- /*
- * Setcursor() - Set the cursor to the specified location.
- */
-
- static void Setcursor (int line, int col)
- {
- Regs.h.ah = GET_VMODE;
- INT86_FN( VIDEO_INT, &Regs, &Regs );
-
- Regs.h.dh = MIN(line, Ymax - 1);
- Regs.h.dl = MIN(col, Xmax - 1);
- Regs.h.ah = SET_POSN;
- INT86_FN(VIDEO_INT, &Regs, &Regs);
- }
-
- /*
- * Dosrestore() - Restore the screen to what it was before we started()'d
- */
-
- static void Dosrestore (void)
- {
- if (Oldscreen != NULL)
- {
- #if defined (__WATCOMC__) && defined (__386__)
- char *scr_ptr = (Screenbase << 4);
- memcpy(scr_ptr, Oldscreen, Xmax * Ymax * 2);
- #else
- movedata(GetDS(), (unsigned) Oldscreen, Screenbase, 0, Xmax * Ymax * 2);
- #endif
- }
- }
-
- /*
- * Kbhit() - Returns TRUE if a character in the k/b buffer, else FALSE.
- */
-
- static bool Kbhit (void)
- {
- return kbhit();
- }
-
- static int Getkey (bool raw)
- {
- int c;
-
- if (raw)
- return getch();
-
- c = getch();
- if (c == 0)
- c = getch() | 0x100;
-
- if (c >= SCAN_F1 && c <= SCAN_F1+9)
- return KEY_F(c-SCAN_F1+1);
- if (c >= SCAN_SF1 && c <= SCAN_SF1+9)
- return KEY_F(c-SCAN_SF1+11);
- if (c >= SCAN_CF1 && c <= SCAN_CF1+9)
- return KEY_F(c-SCAN_CF1+21);
- if (c >= SCAN_AF1 && c <= SCAN_AF1+9)
- return KEY_F(c-SCAN_AF1+31);
-
- switch (c) {
- case SCAN_DOWN: return KEY_DOWN;
- case SCAN_UP: return KEY_UP;
- case SCAN_LEFT: return KEY_LEFT;
- case SCAN_RIGHT: return KEY_RIGHT;
- case SCAN_HOME: return KEY_HOME;
- case SCAN_BACKSPACE: return KEY_BACKSPACE;
- case SCAN_DC: return KEY_DC;
- case SCAN_IC: return KEY_IC;
- case SCAN_NPAGE: return KEY_NPAGE;
- case SCAN_PPAGE: return KEY_PPAGE;
- case SCAN_CNPAGE: return KEY_SF;
- case SCAN_CPPAGE: return KEY_SR;
- case SCAN_BTAB: return KEY_BTAB;
- case SCAN_END: return KEY_END;
- case SCAN_EXIT: return KEY_EXIT;
- case SCAN_SEND: return KEY_SEND;
- case SCAN_SHOME: return KEY_SHOME;
- case SCAN_SLEFT: return KEY_SLEFT;
- case SCAN_SRIGHT: return KEY_SRIGHT;
- default:
- return c & 0xff;
- }
- }
-